package com.zynn.service.module.es.service;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.google.common.collect.Lists;
import com.zynn.service.module.es.bo.DegOneFrientWithWeight;
import com.zynn.service.module.es.constant.ConstantUtil;
import com.zynn.service.module.es.dao.UserFriendMapper;
import com.zynn.service.module.es.entity.ProductBaseUserCache;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 刘猛
 * @description 初始化高校每个用户的一度好友
 * @create 2018-09-14
 **/
@Slf4j
@Service
public class InitVersionProfileUserFriendsService {

    @Autowired
    private RestHighLevelClient client;

    @Autowired
    UserFriendMapper userFriendMapper;

    @Autowired
    InitProductUserFriendsService initProductUserFriendsService;

    /**
     * 权重分数100分
     */
    private static final int SCORE100 = 100;
    /**
     * 权重分数80分
     */
    private static final int SCORE80 = 80;

    private static final int CALC_TYPE_01 = 1;
    private static final int CALC_TYPE_02 = 2;


    private static final int DEG_ONE = 1;
    private static final int DEG_TWO = 2;


    /**
     * 计算用户的推荐好友
     * @param userId
     */
    public void initVersionProfileUserFriendsWithWeight(Long inviteUserId,Long beInvitedUserId) {
        List<DegOneFrientWithWeight> recommendListDegAll = this.queryUserRecommendWithWeightDegAll(inviteUserId);
        if(!CollectionUtils.isEmpty(recommendListDegAll)){
            List<String> friendsWithWeight = recommendListDegAll.stream().map((e) -> e.getWeight() +"|"+ e.getUserId()).collect(Collectors.toList());
            this.syncProfileDegOneFriends(inviteUserId,friendsWithWeight);
        }

    }

    /**
     * 将推荐好友信息同步到es
     * @param userId
     * @param userIdList
     * @param friendWithWeight
     */
    private void syncProfileDegOneFriends(Long userId,List<String> friendWithWeight) {
        if(RecommandUtil.existsIndex(userId,client)){
            this.updateProfileIndex(userId,friendWithWeight);
        }else{
            this.createProfileIndex(userId,friendWithWeight);
        }
    }

    /**
     * 个人资料版推荐索引（更新）
     * @param userId
     * @param friendWithWeight
     */
    private void updateProfileIndex(Long userId,List<String> friendWithWeight){
        Map<String, Object> jsonMap = new HashMap<>(20);
        jsonMap.put("profile_user_friend_with_weight", friendWithWeight);

        //Map会自动转换为JSON格式的文档源
        UpdateRequest indexRequest = new UpdateRequest("user_friend_index", "_doc", userId.toString())
                .doc(jsonMap);
        UpdateResponse indexResponse = null;
        try {
            indexResponse = client.update(indexRequest);
            log.info(indexResponse.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 个人资料版推荐索引（创建）
     * @param userId
     * @param friendWithWeight
     */
    private void createProfileIndex(Long userId,List<String> friendWithWeight){
        Map<String, Object> jsonMap = new HashMap<>(20);
        jsonMap.put("user_id", userId);
        jsonMap.put("profile_user_friend_with_weight", friendWithWeight);

        //Map会自动转换为JSON格式的文档源
        IndexRequest indexRequest = new IndexRequest("user_friend_index", "_doc", userId.toString())
                .source(jsonMap);
        IndexResponse indexResponse = null;
        try {
            indexResponse = client.index(indexRequest);
            log.info(indexResponse.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public List<DegOneFrientWithWeight> queryUserRecommendWithWeightDegAll(Long userId) {
        List<DegOneFrientWithWeight> recommendFriendsAll = Lists.newLinkedList();
        Map<String,Object> params = new HashMap<>(8);

        /**
         * 推荐用户
         */
        this.mergeRecommendUsers(userId,CALC_TYPE_01,SCORE100,params,recommendFriendsAll);
        this.mergeRecommendUsers(userId,CALC_TYPE_02,SCORE80,params,recommendFriendsAll);

        if(!CollectionUtils.isEmpty(recommendFriendsAll)){
            /**
             * 排除自己
             */
            RecommandUtil.removeMyself(recommendFriendsAll,userId);
            /**
             * 推荐用户重复时，选择分数高者
             */
            RecommandUtil.getHightestScoreRecommendUser(recommendFriendsAll);
        }
        return recommendFriendsAll;
    }


    /**
     * 根据计算类型获取不同的推荐计算逻辑方法
     * @param userId
     * @param calcType 计算类型
     * @param score 分数
     * @param params 参数
     * @param allRecommendList 推荐总集合
     */
    public void mergeRecommendUsers(Long userId,int calcType,int score,Map<String,Object> params,List<DegOneFrientWithWeight> allRecommendList){
        params.clear();
        params.put("userId",userId);
        params.put("score",score);
        List<DegOneFrientWithWeight> reommendList = null;
        switch (calcType){
            case CALC_TYPE_01: reommendList = userFriendMapper.queryUserRecommendCondOne(params);break;
            case CALC_TYPE_02: reommendList = userFriendMapper.queryUserRecommendCondTwo(params);break;
            default: break;
        }
        if(!CollectionUtils.isEmpty(reommendList)){
            allRecommendList.addAll(reommendList);
        }
    }


}
